package com.wolfking.jeesite.freemarker;

import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.ui.freemarker.SpringTemplateLoader;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;

@Slf4j
public abstract class AbstractFreemarkerTemplateConfig implements InitializingBean, FreemarkerCustomConfig {

    @Autowired
    protected Configuration configuration;

    private TemplateLoader get() {
        final DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        try {
            return new FileTemplateLoader(resourceLoader.getResource(getPath()).getFile()) {
                @Override
                public Reader getReader(Object templateSource, String encoding) throws IOException {
                    if (isEncryption()) {
                        return decrypt(super.getReader(templateSource, encoding));
                    } else {
                        return super.getReader(templateSource, encoding);
                    }
                }
            };
        } catch (Exception exception) {
            return new SpringTemplateLoader(resourceLoader, getPath()) {
                @NonNull
                @Override
                public Reader getReader(@NonNull Object templateSource, @NonNull String encoding) throws IOException {
                    if (isEncryption()) {
                        return decrypt(super.getReader(templateSource, encoding));
                    } else {
                        return super.getReader(templateSource, encoding);
                    }
                }
            };
        }
    }

    protected void beforeInitTemplateLoader() {

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        beforeInitTemplateLoader();
        log.info("init the [{}] freemarker template,{}", getDesc(), getPath());
        TemplateLoader templateLoader = configuration.getTemplateLoader();
        if (templateLoader instanceof MultiTemplateLoader) {
            MultiTemplateLoader multiTemplateLoader = (MultiTemplateLoader) templateLoader;
            Field field = MultiTemplateLoader.class.getDeclaredField("templateLoaders");
            field.setAccessible(true);
            TemplateLoader[] templateLoaders = (TemplateLoader[]) field.get(multiTemplateLoader);
            TemplateLoader[] newTemplateLoader = new TemplateLoader[templateLoaders.length + 1];
            System.arraycopy(templateLoaders, 0, newTemplateLoader, 0, templateLoaders.length);
            TemplateLoader current = get();
            newTemplateLoader[newTemplateLoader.length - 1] = current;
            boolean sticky = multiTemplateLoader.isSticky();
            MultiTemplateLoader newMultiTemplateLoader = new MultiTemplateLoader(newTemplateLoader);
            newMultiTemplateLoader.setSticky(sticky);
            configuration.setTemplateLoader(newMultiTemplateLoader);
        } else {
            TemplateLoader[] newTemplateLoader = new TemplateLoader[2];
            newTemplateLoader[0] = templateLoader;
            newTemplateLoader[1] = get();
            MultiTemplateLoader newMultiTemplateLoader = new MultiTemplateLoader(newTemplateLoader);
            configuration.setTemplateLoader(newMultiTemplateLoader);
        }
        log.info("init the [{}] freemarker template success", getDesc());
    }
}
